using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Diagnostics;
using Blazing.BusinessObjects.Geocode.RawObjects;
using System.Drawing;
using System.BusinessObjects.Helpers;
using System.Configuration;
using Blazing.BusinessObjects.Locations;

namespace Blazing.BusinessObjects.RESTAgent
{
    public class RESTAgent
    {
        private static T getResponseXml<T>(string restUrl)
        {
            System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(restUrl);
            request.Method = "GET";

            //Authentication code for future webservices that might need them...?
            //request.PreAuthenticate = true;
            //request.Credentials = new System.Net.NetworkCredential(Username, Password);

            return XmlHelper.Deserialise<T>(request.GetResponse().GetResponseStream());
        }

        public static Blazing.BusinessObjects.Cms.Geocode GetGoogleGeocode(Blazing.BusinessObjects.Locations.Address loc)
        {
            string apikey = ConfigurationManager.AppSettings["GoogleAPIKey"];
            return GetGoogleGeocode(loc, apikey);
        }

        public static Blazing.BusinessObjects.Cms.Geocode GetGoogleGeocode(Blazing.BusinessObjects.Locations.Location loc)
        {
            string apikey = ConfigurationManager.AppSettings["GoogleAPIKey"];
            Blazing.BusinessObjects.Locations.Address addr = new Blazing.BusinessObjects.Locations.Address();

            Location topLocation = loc;
            while (topLocation.ParentLocation != null)
                topLocation = topLocation.ParentLocation;

            if (topLocation != loc) //use country and innerloc
            {
                addr.Suburb = loc.Namelong;
            }
            addr.Country = new Country();
            addr.State = new State();
            addr.Country.Name = topLocation.Namelong;

            return GetGoogleGeocode(addr, apikey);
        }

        /// <summary>
        /// Appends geocoding information to a location from google
        /// </summary>
        public static Blazing.BusinessObjects.Cms.Geocode GetGoogleGeocode(Blazing.BusinessObjects.Locations.Address loc, string apikey)
        {
            Blazing.BusinessObjects.Cms.Geocode retval = new Blazing.BusinessObjects.Cms.Geocode();

            string url =
                string.Format("http://maps.google.com/maps/geo?key={0}&q={1}{2}+{3},{4},{5}&output=xml", apikey, loc.Address1, loc.Address2, loc.Suburb, loc.State.Name, loc.Country.Name);

            //kmlGeocode
            kmlGeocode code = getResponseXml<kmlGeocode>(url);
            kmlResponse item = code.Items[0];

            if (item.Placemark != null && item.Placemark.Length > 0)
            {
                kmlResponsePlacemark placemark = item.Placemark[0];

                Trace.WriteLine(placemark.Point.coordinates);

                if (item.Status.code != "200")
                {
                    throw new ApplicationException("Wrong status code returned: " + code.Items[0].Status.code);
                }

                if (placemark.AddressDetails != null)
                {
                    retval.Accuracy = int.Parse(placemark.AddressDetails.Accuracy);

                    //set corrective address
                    if(placemark.AddressDetails.Country.AdministrativeArea.Locality.PostalCode != null)
                        loc.Postcode = placemark.AddressDetails.Country.AdministrativeArea.Locality.PostalCode.PostalCodeNumber;
                    if(placemark.AddressDetails.Country.AdministrativeArea.Locality.Thoroughfare != null)
                        loc.Address1 = placemark.AddressDetails.Country.AdministrativeArea.Locality.Thoroughfare.ThoroughfareName;
                    if(placemark.AddressDetails.Country.AdministrativeArea.Locality != null)
                        loc.Suburb = placemark.AddressDetails.Country.AdministrativeArea.Locality.LocalityName;
                }
                else
                {
                    retval.Accuracy = -1;
                }

                string[] coords = placemark.Point.coordinates.Split(',');

                retval.Longatude = double.Parse(coords[0]);
                retval.Latitude = double.Parse(coords[1]);
                retval.HashLookup = Blazing.BusinessObjects.Cms.Geocode.CalculateMD5Hash(loc);
                loc.Geocode = retval;

                return retval;
            }
            else
            {
                return new Blazing.BusinessObjects.Cms.Geocode();
            }
        }
    }
}
